/*
Copyright 2000-2011 Francois de Bertrand de Beuvron

This file is part of CoursBeuvron.

CoursBeuvron is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

CoursBeuvron is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with CoursBeuvron.  If not, see <http://www.gnu.org/licenses/>.
 */
package fr.insa.beuvron.tps.m2.dessin2DV3.gui;

import fr.insa.beuvron.tps.m2.dessin2DV3.Figure;
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

/**
 *
 * @author beuvronfr
 */
public class FigurePanel extends JPanel {

    public static int MARGE_PAR_DEFAUT = 5;
    private Figure fig;
    private int marge;
    private AffineTransform curTrans;

    /** Attention, vous devez définir la figure avant d'utiliser ce panel */
    public FigurePanel() {
        this.fig = fig;
        this.marge = MARGE_PAR_DEFAUT;
        this.curTrans = new AffineTransform();
    }

    /** Creates a new instance of PanelPourFigure */
    public FigurePanel(Figure fig) {
        this.fig = fig;
        this.marge = MARGE_PAR_DEFAUT;
        this.curTrans = new AffineTransform();
    }

    /**
     * calcule la transformation permettant de contenir toute la figure.
     * Attention : la taille d'un JPanel n'est en général connue que 
     * lorque le JPanel est intégré dans une fenêtre. Cette méthode ne devrait
     * donc être appelée qu'après que le FigurePanel ait été placé dans une fenetre (JFrame)
     */
    public AffineTransform transToFit() {
        int largeurFenetre = this.getWidth() - 2 * this.marge;
        int hauteurFenetre = this.getHeight() - 2 * this.marge;
        if (largeurFenetre <= 0 || hauteurFenetre <= 0) {
            return new AffineTransform();
        } else {
            double largeurFigure = this.getFig().maxX() - this.getFig().minX();
            double hauteurFigure = this.getFig().maxY() - this.getFig().minY();
            double scale = Math.max(largeurFigure / largeurFenetre, hauteurFigure / hauteurFenetre);
            if (scale == 0) {
                scale = 1;
            }
            AffineTransform trans = new AffineTransform();
            trans.preConcatenate(AffineTransform.getTranslateInstance(-this.fig.minX(), -this.fig.minY()));
            trans.preConcatenate(AffineTransform.getScaleInstance(1 / scale, 1 / scale));
            trans.preConcatenate(AffineTransform.getTranslateInstance(this.marge, this.marge));
            return trans;
        }
    }
    
    /**
     * voir remarque dans {@link #transToFit() }
     */
    public void zoomToFit() {
        this.setCurTrans(this.transToFit());
        this.repaint();
    }
    
    public void zoomFacteur(double facteur) {
        curTrans.preConcatenate(AffineTransform.getScaleInstance(facteur, facteur));
        this.repaint();
    }
    
    /**
     * transforme une position du repère des figures vers le repere du panel
     * @param coordFigure
     * @return 
     */
    public double[] coordPanel(double[] coordFigure) {
        double[] res =  new double[2];
        this.curTrans.transform(coordFigure, 0,res, 0, 1);
        return res;
    }

    /**
     * transforme une position du repère du panel vers le repere des figures
     * @param coordFigure
     * @return 
     */
    public double[] coordFigure(double[] coordPanel) {
        double[] res =  new double[2];
        try {
            this.curTrans.inverseTransform(coordPanel, 0,res, 0, 1);
        } catch (NoninvertibleTransformException ex) {
            throw new Error(ex);
        }
        return res;
    }

    public Figure getADessiner() {
        return getFig();
    }

    public void setADessiner(Figure aDessiner) {
        this.setFig(aDessiner);
    }

    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2 = (Graphics2D) g;
        if (this.fig != null) {
            this.fig.dessine(g2, this.curTrans);
        }
    }

    public int getMarge() {
        return marge;
    }

    public void setMarge(int marge) {
        this.marge = marge;
    }

    public static void affichageTest(Figure fig, int largeurFenetre, int hauteurFenetre) {
        JFrame fen = new JFrame("dessin de figure");
        fen.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        fen.setSize(largeurFenetre, hauteurFenetre);
        FigurePanel ppf = new FigurePanel(fig);
        fen.add(ppf);
        fen.setVisible(true);
        ppf.zoomToFit();
        ppf.repaint();
    }

    /**
     * @return the curTrans
     */
    public AffineTransform getCurTrans() {
        return curTrans;
    }

    /**
     * @param curTrans the curTrans to set
     */
    public void setCurTrans(AffineTransform curTrans) {
        this.curTrans = curTrans;
    }

    /**
     * @return the fig
     */
    public Figure getFig() {
        return fig;
    }

    /**
     * @param fig the fig to set
     */
    public void setFig(Figure fig) {
        this.fig = fig;
        this.repaint();
    }
}
